package com.xiaomaoguai.netty;

import io.netty.bootstrap.Bootstrap;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;

import java.nio.charset.Charset;
import java.util.Date;
import java.util.concurrent.TimeUnit;

/**
 * @fileName: ClientServer.java
 * @author: WeiHui
 * @date: 2018/9/30 17:07
 * @version: v1.0.0
 * @since JDK 1.8
 */
public class ClientServer {

	public static final String HOST = "127.0.0.1";

	public static final int POST = 8000;

	public static final int MAX_TIMES = 5;

	public static void main(String[] args) {
		NioEventLoopGroup workGroup = new NioEventLoopGroup();
		Bootstrap bootstrap = new Bootstrap();

		bootstrap.group(workGroup)
				.channel(NioSocketChannel.class)
				.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 5000)
				.option(ChannelOption.SO_KEEPALIVE, true)
				.option(ChannelOption.TCP_NODELAY, true)
				.handler(new ChannelInitializer<SocketChannel>() {

					@Override
					protected void initChannel(SocketChannel ch) throws Exception {
						ch.pipeline().addLast(new ChannelInboundHandlerAdapter() {

							@Override
							public void channelActive(ChannelHandlerContext ctx) throws Exception {
								ByteBuf buffer = ctx.alloc().buffer();
								byte[] bytes = "好好学习".getBytes(Charset.forName("UTF-8"));
								buffer.writeBytes(bytes);
								ctx.channel().writeAndFlush(buffer);
							}

							@Override
							public void channelRead(ChannelHandlerContext ctx, Object msg) {
								ByteBuf byteBuf = (ByteBuf) msg;

								System.out.println(new Date() + ": 客户端读到数据 -> " + byteBuf.toString(Charset.forName("utf-8")));
							}
						});
					}
				});

		connect(bootstrap, MAX_TIMES);

	}

	private static void connect(Bootstrap bootstrap, int times) {
		bootstrap.connect(HOST, POST).addListener(f -> {
			if (f.isSuccess()) {
				System.out.println("连接成功");
			} else if (times == 0) {
				System.out.println("重试次数耗尽");
			} else {
				int retry = MAX_TIMES - times + 1;
				int delay = retry << 1;
				bootstrap.config().group().schedule(() -> connect(bootstrap, times - 1), delay, TimeUnit.SECONDS);
			}
		});
	}
}
